/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.xtd.facade.employment;

import com.xtd.facade.AbstractFacade;
import com.xtd.facade.SystemException;
import com.xtd.model.employment.DepartmentPost;
import com.xtd.model.employment.Employee;
import com.xtd.model.employment.Payroll;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;

/**
 *
 * @author Lu Yuanbin
 */
@Stateless
public class PayrollFacade extends AbstractFacade<Payroll> {

    public PayrollFacade() {
        super(Payroll.class);
    }

    public List<Payroll> calculatePayroll(Employee[] employees, Date startDate, Date endDate, Employee createdBy) throws SystemException {
        List payrolls = new ArrayList();
        Map<DepartmentPost, PayrollCalculator> payrollCalculatorMap = new HashMap();
        PayrollCalculator payrollCalculator = null;
        for (Employee e : employees) {
            if (e.getLastPayroll() != null) {
                Calendar c = new GregorianCalendar();
                c.setTime(startDate);
                c.add(Calendar.DAY_OF_MONTH, -1);
                Date lastPayrollEndDate = c.getTime();
                if (e.getLastPayroll().getEndDate().equals(lastPayrollEndDate)) {
                    throw new SystemException("员工:" + e.getName() + " 本次工资派发日期与上次不符，起始日期需为上次派发的下一天。");
                }
            }
            if (!payrollCalculatorMap.containsKey(e.getDepartmentPost())) {
                if (e.getDepartmentPost().getPayrollCalculator() != null ) {
                    payrollCalculator = generatePayrollCalculator(e.getDepartmentPost());
                    payrollCalculatorMap.put(e.getDepartmentPost(), payrollCalculator);
                } else {
                    payrollCalculatorMap.put(e.getDepartmentPost(), null);
                }
            }

            if (payrollCalculatorMap.get(e.getDepartmentPost()) != null) {
                payrolls.add(payrollCalculatorMap.get(e.getDepartmentPost()).calculatePayroll(getEntityManager(),e, startDate, endDate, createdBy));
            } else {
                payrolls.add(new Payroll(e, startDate, endDate, createdBy));
            }
        }
        return payrolls;
    }

    public void update(List<Payroll> payrolls, Employee lastModifiedBy) {
        for (Payroll p : payrolls) {
            p.setLastModifiedBy(lastModifiedBy);
            p.getEmployee().setLastPayroll(p);
            getEntityManager().merge(p.getEmployee());
        }
    }

    private PayrollCalculator generatePayrollCalculator(DepartmentPost departmentPost) throws SystemException {
        PayrollCalculator calculator = null;

        try {
            Class a = Class.forName(departmentPost.getPayrollCalculator().getCalculator());
            Constructor c = a.getConstructor(new Class[]{});
            calculator = (PayrollCalculator) c.newInstance(new Object[]{});
        } catch (InstantiationException ex) {
            Logger.getLogger(PayrollFacade.class.getName()).log(Level.SEVERE, null, ex);
            throw new SystemException("无法生成工资计算公式:" + departmentPost.getPayrollCalculator(), ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(PayrollFacade.class.getName()).log(Level.SEVERE, null, ex);
            throw new SystemException("无法生成工资计算公式:" + departmentPost.getPayrollCalculator(), ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(PayrollFacade.class.getName()).log(Level.SEVERE, null, ex);
            throw new SystemException("无法生成工资计算公式:" + departmentPost.getPayrollCalculator(), ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(PayrollFacade.class.getName()).log(Level.SEVERE, null, ex);
            throw new SystemException("无法生成工资计算公式:" + departmentPost.getPayrollCalculator(), ex);
        } catch (NoSuchMethodException ex) {
            Logger.getLogger(PayrollFacade.class.getName()).log(Level.SEVERE, null, ex);
            throw new SystemException("无法生成工资计算公式:" + departmentPost.getPayrollCalculator(), ex);
        } catch (SecurityException ex) {
            Logger.getLogger(PayrollFacade.class.getName()).log(Level.SEVERE, null, ex);
            throw new SystemException("无法生成工资计算公式:" + departmentPost.getPayrollCalculator(), ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(PayrollFacade.class.getName()).log(Level.SEVERE, null, ex);
            throw new SystemException("无法生成工资计算公式:" + departmentPost.getPayrollCalculator(), ex);
        }
        return calculator;
    }
}
